import { Config, Provide } from '@midwayjs/decorator'
import { IWebMiddleware, IMidwayWebNext } from '@midwayjs/web'
import { createProxyMiddleware } from 'http-proxy-middleware'

import * as micromatch from 'micromatch'
import * as isGlob from 'is-glob'

const c2k = require('koa-connect')

function match(context: string, path: string): boolean {
  // single path
  if (!isGlob(context)) {
    return path.indexOf(context) === 0
  }
  // single glob path
  const matches = micromatch([path], context)

  return matches?.length > 0
}

@Provide()
export class ProxyMiddleware implements IWebMiddleware {

  @Config('proxy')
  config: any

  resolve() {
    return async (ctx, next: IMidwayWebNext) => {
      // https://github.com/daysai/egg-http-proxy-middleware/blob/master/src/index.ts
      for (const path of Object.keys(this.config)) {
        if (match(path, ctx.path)) {
          const options = this.config[path]
          const { onProxyReq } = options

          await c2k(
            createProxyMiddleware(path, {
              ...options,
              onProxyReq(proxyReq, req, res) {
                if (onProxyReq && typeof onProxyReq === 'function') {
                  // expose state
                  onProxyReq(proxyReq, req, res, ctx.state)
                }
                // reset rawBody after bodyparser
                const { rawBody, body: requestBody } = ctx.request

                if (requestBody && rawBody) {
                  proxyReq.setHeader('Content-Length', Buffer.byteLength(rawBody))
                  proxyReq.write(rawBody)
                  proxyReq.end()
                }

                return proxyReq
              }
            }) as any
          )(ctx, next)
        }
      }
      await next()
    }
  }
}
